home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 028a / unzup41e.zip / MISC.C < prev    next >
C/C++ Source or Header  |  1991-05-04  |  17KB  |  462 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.   misc.c
  4.  
  5.   This file contains a number of useful but not particularly closely related
  6.   functions; their main claim to fame is that they don't change much, so
  7.   this file should rarely need to be recompiled.  The CRC-32 stuff is from
  8.   crc32.c; do_string() is from nunzip.c; a_to_e() is from ascebc.c; makeword/
  9.   makelong() are from unzip.c; and memset() and memcpy() are from zmemset.c
  10.   and zmemcpy.c, respectively.  Lumped together here to cut down on the size
  11.   of unzip.c and the number of associated files floating around.
  12.  
  13.   ---------------------------------------------------------------------------
  14.  
  15.   Contributions by C. Mascott, Allan Bjorklund, Bill Davidsen, Bo Kullmar,
  16.   Warner Losh, Greg Roelofs, Larry Jones, Mark Edwards, Antoine Verheijen,
  17.   and probably many others.
  18.  
  19.   ---------------------------------------------------------------------------
  20.  
  21.   Copyright, applying to UpdateCRC() and crc_32_tab[]:
  22.  
  23.      COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or code
  24.      or tables extracted from it, as desired without restriction.
  25.  
  26.   ---------------------------------------------------------------------------*/
  27.  
  28.  
  29. #include "unzip.h"
  30.  
  31.  
  32.  
  33. /**************************/
  34. /*  Function UpdateCRC()  */
  35. /**************************/
  36.  
  37.  /*--------------------------------------------------------------------
  38.  
  39.    First, the polynomial itself and its table of feedback terms.  The
  40.    polynomial is
  41.    X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
  42.  
  43.    Note that we take it "backwards" and put the highest-order term in
  44.    the lowest-order bit.  The X^32 term is "implied"; the LSB is the
  45.    X^31 term, etc.  The X^0 term (usually shown as "+1") results in
  46.    the MSB being 1.
  47.  
  48.    Note that the usual hardware shift register implementation, which
  49.    is what we're using (we're merely optimizing it by doing eight-bit
  50.    chunks at a time) shifts bits into the lowest-order term.  In our
  51.    implementation, that means shifting towards the right.  Why do we
  52.    do it this way?  Because the calculated CRC must be transmitted in
  53.    order from highest-order term to lowest-order term.  UARTs transmit
  54.    characters in order from LSB to MSB.  By storing the CRC this way,
  55.    we hand it to the UART in the order low-byte to high-byte; the UART
  56.    sends each low-bit to hight-bit; and the result is transmission bit
  57.    by bit from highest- to lowest-order term without requiring any bit
  58.    shuffling on our part.  Reception works similarly.
  59.  
  60.    The feedback terms table consists of 256, 32-bit entries.  Notes:
  61.  
  62.        The table can be generated at runtime if desired; code to do so
  63.        is shown later.  It might not be obvious, but the feedback
  64.        terms simply represent the results of eight shift/xor opera-
  65.        tions for all combinations of data and CRC register values.
  66.  
  67.        The values must be right-shifted by eight bits by the "updcrc"
  68.        logic; the shift must be unsigned (bring in zeroes).  On some
  69.        hardware you could probably optimize the shift in assembler by
  70.        using byte-swap instructions.
  71.        polynomial $edb88320
  72.  
  73.    --------------------------------------------------------------------*/
  74.  
  75. ULONG crc_32_tab[] =
  76. {
  77.     0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  78.     0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  79.     0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  80.     0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  81.     0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  82.     0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  83.     0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  84.     0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  85.     0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  86.     0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  87.     0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  88.     0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  89.     0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  90.     0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  91.     0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  92.     0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  93.     0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  94.     0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  95.     0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  96.     0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  97.     0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  98.     0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  99.     0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  100.     0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  101.     0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  102.     0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  103.     0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  104.     0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  105.     0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  106.     0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  107.     0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  108.     0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  109.     0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  110.     0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  111.     0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  112.     0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  113.     0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  114.     0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  115.     0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  116.     0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  117.     0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  118.     0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  119.     0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  120.     0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  121.     0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  122.     0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  123.     0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  124.     0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  125.     0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  126.     0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  127.     0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  128.     0x2d02ef8dL
  129. };
  130.  
  131.  
  132. void UpdateCRC(s, len)
  133. register byte *s;
  134. register int len;
  135.  /* update running CRC calculation with contents of a buffer */
  136. {
  137.     register ULONG crcval = crc32val;
  138.  
  139.  
  140.     while (len--)
  141.         crcval = crc_32_tab[((byte) crcval ^ (*s++)) & 0xff] ^ (crcval >> 8);
  142.     crc32val = crcval;
  143. }
  144.  
  145.  
  146.  
  147.  
  148.  
  149. /**************************/
  150. /*  Function do_string()  */
  151. /**************************/
  152.  
  153. int do_string(len, option)      /* return PK-type error code */
  154. unsigned int len;               /* without prototype, UWORD converted to this */
  155. int option;
  156. {
  157.     int block_length, error = 0;
  158.     UWORD comment_bytes_left, extra_len;
  159.  
  160.  
  161.  
  162. /*---------------------------------------------------------------------------
  163.     This function processes arbitrary-length (well, usually) strings.  Three
  164.     options are allowed:  SKIP, wherein the string is skipped pretty logical,
  165.     eh?); DISPLAY, wherein the string is printed to standard output after un-
  166.     dergoing any necessary or unnecessary character conversions; and FILENAME,
  167.     wherein the string is put into the filename[] array after undergoing ap-
  168.     propriate conversions (including case-conversion, if that is indicated:
  169.     see the global variable lcflag).  The latter option should be OK, since
  170.     filename is now dimensioned at FILENAME_MAX (1024).
  171.  
  172.     The string, by the way, is assumed to start at the current file-pointer
  173.     position; its length is given by len.  So start off by checking length
  174.     of string:  if zero, we're already set.
  175.   ---------------------------------------------------------------------------*/
  176.  
  177.     if (!len)
  178.         return (0);             /* 0:  no error */
  179.  
  180.     switch (option) {
  181.  
  182.     /*
  183.      * First case:  print string on standard output.  First set loop vari-
  184.      * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
  185.      * converting formats and printing as we go.  The second half of the
  186.      * loop conditional was added because the file might be truncated, in
  187.      * which case comment_bytes_left will remain at some non-zero value for
  188.      * all time.  outbuf is used as a scratch buffer because it is avail-
  189.      * able (we should be either before or in between any file processing).
  190.      * [The typecast in front of the min() macro was added because of the
  191.      * new promotion rules under ANSI C; readbuf() wants an int, but min()
  192.      * returns a signed long, if I understand things correctly.  The proto-
  193.      * type should handle it, but just in case...]
  194.      */
  195.  
  196.     case DISPLAY:
  197.         comment_bytes_left = len;
  198.         block_length = OUTBUFSIZ;    /* for the while statement, first time */
  199.         while (comment_bytes_left > 0 && block_length > 0) {
  200.             if ((block_length = readbuf((char *) outbuf,
  201.                          (int) min(OUTBUFSIZ, comment_bytes_left))) <= 0)
  202.                 return (51);    /* 51:  unexpected EOF */
  203.             comment_bytes_left -= block_length;
  204.             NUKE_CRs(outbuf, block_length);     /* (modifies block_length) */
  205.  
  206.             /*  this is why we allocated an extra byte for outbuf: */
  207.             outbuf[block_length] = '\0';        /* terminate w/zero:  ASCIIZ */
  208.  
  209.             A_TO_N(outbuf);     /* translate string to native */
  210.  
  211.             printf("%s", outbuf);
  212.         }
  213.         printf("\n", outbuf);   /* assume no newline at end */
  214.         break;
  215.  
  216.     /*
  217.      * Second case:  read string into filename[] array.  The filename should
  218.      * never ever be longer than FILNAMSIZ (1024), but for now we'll check,
  219.      * just to be sure.
  220.      */
  221.  
  222.     case FILENAME:
  223.         extra_len = 0;
  224.         if (len >= FILNAMSIZ) {
  225.             fprintf(stderr, "warning:  filename too long--truncating.\n");
  226.             error = 1;          /* 1:  warning error */
  227.             extra_len = len - FILNAMSIZ + 1;
  228.             len = FILNAMSIZ - 1;
  229.         }
  230.         if (readbuf(filename, len) <= 0)
  231.             return (51);        /* 51:  unexpected EOF */
  232.         filename[len] = '\0';   /* terminate w/zero:  ASCIIZ */
  233.  
  234.         A_TO_N(filename);       /* translate string to native */
  235.  
  236.         if (lcflag)
  237.             TOLOWER(filename, filename);        /* replace with lowercase fn. */
  238.  
  239.         if (!extra_len)         /* we're done here */
  240.             break;
  241.  
  242.         /*
  243.          * We truncated the filename, so print what's left and then fall
  244.          * through to the SKIP routine.
  245.          */
  246.         fprintf(stderr, "[ %s ]\n", filename);
  247.         len = extra_len;
  248.         /*  FALL THROUGH...  */
  249.  
  250.     /*
  251.      * Third case:  skip string, adjusting readbuf's internal variables
  252.      * as necessary (and possibly skipping to and reading a new block of
  253.      * data).
  254.      */
  255.  
  256.     case SKIP:
  257.         LSEEK(cur_zipfile_bufstart + (inptr-inbuf) + len)
  258.         break;
  259.  
  260.     }                           /* end switch (option) */
  261.  
  262.     return (error);
  263.  
  264. }                               /* end function do_string() */
  265.  
  266.  
  267.  
  268.  
  269.  
  270. #ifdef EBCDIC
  271.  
  272. /*
  273.  * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
  274.  * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
  275.  */
  276.  
  277. unsigned char ebcdic[] =
  278. {
  279.     0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  280.     0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
  281.     0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
  282.     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
  283.     0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
  284.     0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xba, 0xe0, 0xbb, 0xb0, 0x6d,
  285.     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
  286.     0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
  287.     0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
  288.     0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xff,
  289.     0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5, 0xbd, 0xb4, 0x9a, 0x8a, 0x5f, 0xca, 0xaf, 0xbc,
  290.     0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3, 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
  291.     0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68, 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
  292.     0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf, 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xad, 0xae, 0x59,
  293.     0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48, 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
  294.     0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1, 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf
  295. };
  296.  
  297. #endif                          /* EBCDIC */
  298.  
  299.  
  300.  
  301.  
  302.  
  303. #ifdef NOTINT16
  304.  
  305. /*************************/
  306. /*  Function makeword()  */
  307. /*************************/
  308.  
  309. UWORD makeword(b)
  310. byte *b;
  311.  /*
  312.   * Convert Intel style 'short' integer to non-Intel non-16-bit
  313.   * host format.  This routine also takes care of byte-ordering.
  314.   */
  315. {
  316. /*
  317.     return  ( ((UWORD)(b[1]) << 8)  |  (UWORD)(b[0]) );
  318.  */
  319.     return ((b[1] << 8) | b[0]);
  320. }
  321.  
  322.  
  323.  
  324.  
  325.  
  326. /*************************/
  327. /*  Function makelong()  */
  328. /*************************/
  329.  
  330. ULONG makelong(sig)
  331. byte *sig;
  332.  /*
  333.   * Convert intel style 'long' variable to non-Intel non-16-bit
  334.   * host format.  This routine also takes care of byte-ordering.
  335.   */
  336. {
  337.     return (((ULONG) sig[3]) << 24)
  338.         + (((ULONG) sig[2]) << 16)
  339.         + (((ULONG) sig[1]) << 8)
  340.         + ((ULONG) sig[0]);
  341. }
  342.  
  343. #endif                          /* !NOTINT16 */
  344.  
  345.  
  346.  
  347.  
  348.  
  349. #ifdef VMS
  350.  
  351. /***************************/
  352. /*  Function return_VMS()  */
  353. /***************************/
  354.  
  355. void return_VMS(zip_error)
  356. int zip_error;
  357. {
  358. /*---------------------------------------------------------------------------
  359.     Do our own, explicit processing of error codes and print message, since
  360.     VMS misinterprets return codes as rather obnoxious system errors ("access
  361.     violation," for example).
  362.   ---------------------------------------------------------------------------*/
  363.  
  364. #ifndef NO_RETURN_CODES         /* can compile without messages if want */
  365.     switch (zip_error) {
  366.  
  367.     case 0:
  368.         break;                  /* life is fine... */
  369.     case 1:
  370.         fprintf(stderr, "\n[return-code 1:  warning error \
  371. (e.g., failed CRC or unknown compression method)]\n");
  372.         break;
  373.     case 2:
  374.     case 3:
  375.         fprintf(stderr, "\n[return-code %d:  error in zipfile \
  376. (e.g., can't find local file header sig)]\n",
  377.                 zip_error);
  378.         break;
  379.     case 4:
  380.     case 5:
  381.     case 6:
  382.     case 7:
  383.     case 8:
  384.         fprintf(stderr, "\n[return-code %d:  insufficient memory]\n",
  385.                 zip_error);
  386.         break;
  387.     case 9:
  388.         fprintf(stderr, "\n[return-code 9:  zipfile not found]\n");
  389.         break;
  390.     case 10:                    /* this is the one that gives "access violation," I think */
  391.         fprintf(stderr, "\n[return-code 10:  bad or illegal parameters \
  392. specified on command line]\n");
  393.         break;
  394.     case 11:                    /* I'm not sure this one is implemented, but maybe soon? */
  395.         fprintf(stderr, "\n[return-code 11:  no files found to \
  396. extract/view/etc.]\n");
  397.         break;
  398.     case 50:
  399.         fprintf(stderr, "\n[return-code 50:  disk full \
  400. (or otherwise unable to open output file)]\n");
  401.         break;
  402.     case 51:
  403.         fprintf(stderr, "\n[return-code 51:  unexpected EOF in zipfile \
  404. (i.e., truncated)]\n");
  405.         break;
  406.     default:
  407.         fprintf(stderr, "\n[return-code %d:  unknown return-code \
  408. (who put this one in?  Wasn't me...)]\n",
  409.                 zip_error);
  410.         break;
  411.     }
  412. #endif                          /* NO_RETURN_CODES */
  413.  
  414.     exit(0);                    /* everything okey-dokey as far as VMS concerned */
  415. }
  416.  
  417. #endif                          /* VMS */
  418.  
  419.  
  420.  
  421.  
  422.  
  423. #ifdef ZMEM                     /* memset, memcpy for systems without them */
  424.  
  425. /************************/
  426. /*  Function zmemset()  */
  427. /************************/
  428.  
  429. char *memset(buf, init, len)
  430. register char *buf, init;       /* buffer loc and initializer */
  431. register unsigned int len;      /* length of the buffer */
  432. {
  433.     char *start;
  434.  
  435.     start = buf;
  436.     while (len--)
  437.         *(buf++) = init;
  438.     return (start);
  439. }
  440.  
  441.  
  442.  
  443.  
  444.  
  445. /************************/
  446. /*  Function zmemcpy()  */
  447. /************************/
  448.  
  449. char *memcpy(dst, src, len)
  450. register char *dst, *src;
  451. register unsigned int len;
  452. {
  453.     char *start;
  454.  
  455.     start = dst;
  456.     while (len-- > 0)
  457.         *dst++ = *src++;
  458.     return (start);
  459. }
  460.  
  461. #endif                          /* ZMEM */
  462.